home *** CD-ROM | disk | FTP | other *** search
- /* Functions for moving files. One of the functions will automatically
- use the most efficient method for moving a file: if the source and
- destination are on the same volume it uses CatMove, while if they are
- on different volumes the source file is copied and then deleted.
- Another useful function provides a more portable (ie, system 6.0
- through 7.0 compatible, and compatible with all volumes) implementation
- of FSpExchangeFiles.
-
- 93/10/14 aih
- - file's catalog is copied during a file exchange in a simpler
- manner than before
-
- 93/03/19 AIH
- - Went back to old way of using CatMove since the new way doesn't
- work
-
- 91/05/31 AIH
- - Simplified use of CatMove as described in the latest version (February
- '91) of TN226
-
- 91/05/27 AIH
- - The function for exchanging two files uses FSpExchangeFiles if possible
-
- 91/05/23 AIH
- - The function for exchanging two files is a little more robust
-
- 91/05/17 AIH
- - Fixed possible bug with A/UX and CatMove
-
- 91/05/08 AIH
- - Added function to exchange two files
-
- 91/03/23 Ari Halberstadt (AIH)
- - Fixed bug in way CatMove was called: the routine expects a Pascal string,
- not a C string. */
-
- #include <string.h>
- #include "MacLib.h"
- #include "VolumeLib.h"
- #include "FileLib.h"
-
- /* Move the source file to the destination file. If the source and destination
- are on the same volume then the file isn't actually moved, instead the
- catalog entries are changed by calling CatMove (see TN226). When the
- source and destination are on separate volumes the source is first
- copied to the destination and then the source is deleted. */
- void FileMove(FileType *src, FileType *dst)
- {
- Boolean samevol = false; /* true if the files are on the same volume */
- FileNameType name;
- OSErr err = noErr;
-
- require(FileValid(src));
- require(FileValid(dst));
- /* check for existing destination */
- if (FileExists(dst))
- FailOSErr(dupFNErr);
- /* use a more efficient way of moving the files if they're on the same
- volume */
- samevol = (src->vol == dst->vol);
- if (samevol) {
- err = CatMove(src->vol, src->dir, src->pnm, dst->dir, NULL);
- if (err == badMovErr) {
- /* we're probably on A/UX and it's mapping the volumes so
- that two physically different volumes still have the
- same vRefNum (see TN229) */
- samevol = false;
- err = noErr;
- }
- else {
- /* CatMove keeps the name of the original file, so we rename it
- to use the name of the destination */
- FailOSErr(err);
- strcpy(name, FileName(dst));
- FileNameSet(dst, src->cnm);
- FileRename(dst, name);
- }
- }
- /* if the files aren't on the same volume, copy the source file
- to the destination file and then delete the source file */
- if (! samevol) {
- FileCopy(src, dst);
- FileDelete(src);
- }
- }
-
- /* Under system 7.0 the routine FSpExchangeFiles can be used with certain
- volumes to swap two files when doing a "safe save". To use the routine
- FSpExchangeFiles, the system software must support it, the volume
- containing the files must support it, and both files must be on the same
- volume. If any of these conditions is not met then other File Manager
- routines are used. Unlike the real FspExchangeFiles, both files must be
- closed for this function to work in all cases, since I can't modify the
- File Control Blocks of open files.
-
- In this implementation, the file 'fp1' replaces the file 'fp2'.
- If this function terminates successfully, then the file 'fp1' no longer
- exists, and the old version of the file 'fp2' is discarded. Every effort
- has been made to ensure that the old version of the file 'fp2' is not
- discarded until the file 'fp1' has successfully replaced it.
- All the Finder information of the original file 'fp2', including the
- creation date, is preserved. For greatest efficiency--to avoid having
- to copy the file, instead of moving it by swapping catalog entries, and
- to take advantage of FSpExchangeFiles--'fp1' and 'fp2' should be on
- the same volume, though the function will work even if the files are on
- different volumes.
-
- Unlike the routine FSpExchangeFiles, only the file 'fp1' remains,
- except it is now in the location indicated by 'fp2'. This is
- equivalent to a call to FSpExchangeFiles followed by a call to
- delete the file 'fp1'. In fact, this is exactly what this
- function attempts to do. */
- void FileExchange(FileType *fp1, FileType *fp2)
- {
- CInfoPBRec cat; /* catalog entry for fp1 */
- FileNameType name; /* unique name for fp2 */
- FSSpec spec1; /* spec for fp1 */
- FSSpec spec2; /* spec for fp2 */
- volatile FileType oldfp2; /* renamed fp2 (ie, old version) */
- volatile Boolean renamed = false;
- volatile Boolean moved = false;
-
- require(FileExists(fp1));
- require(FileExists(fp2));
- require(fp1->ref == FILE_CLOSED);
- require(fp2->ref == FILE_CLOSED);
-
- TRY {
- /* use FSpExchangeFiles if possible */
- if (fp1->vol == fp2->vol && VolumeSupportsFSpExchangeFiles(fp1->vol)) {
- FileToFSSpec(fp1, &spec1);
- FileToFSSpec(fp2, &spec2);
- FailOSErr(FSpExchangeFiles(&spec1, &spec2));
- FileDelete(fp1);
- }
- else {
-
- /* remember catalog info */
- FileCatalog(fp2, &cat);
-
- /* move fp2 out of the way by giving it a unique name */
- strcpy(name, FileName(fp2));
- FileUniqueInList(name, fp1, fp2, NULL);
- FileClone(fp2, &oldfp2);
- FileRename(&oldfp2, name);
- renamed = true;
-
- /* move fp1 into the old location of fp2 */
- FileMove(fp1, fp2);
- moved = true;
-
- /* copy catalog info, but use current time as modification time */
- GetDateTime(&cat.hFileInfo.ioFlMdDat);
- FileCatalogSet(fp2, &cat);
-
- /* everything was successful, so remove old copy of fp2 */
- FileDelete(&oldfp2);
-
- ensure(! FileExists(fp1));
- ensure(FileExists(fp2));
- }
- } CATCH {
- if (moved)
- FileMove(fp2, fp1);
- if (renamed)
- FileRename(&oldfp2, FileName(fp2));
- } ENDTRY;
- }
-
-